package com.bishe.cyh.excep;

import com.bishe.cyh.mode.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @Author: Poppin
 * @Date: 2021/12/31 13:14
 * @Version: 1.0
 */


@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler:Code %s Detail: %s";
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    //运行异常
    @ExceptionHandler(RuntimeException.class)
    public Result runtimeExceptionHandler(RuntimeException ex){
        return resultFormat(1,ex,"系统内部故障，请联系管理员");
    }

    //空指针异常
    @ExceptionHandler(NullPointerException.class)
    public Result nullPointerExceptionHandler(NullPointerException ex){
        return resultFormat(2,ex,"系统内部故障，请联系管理员");
    }

    //类型转换异常
    @ExceptionHandler(ClassCastException.class)
    public Result classCastExceptionHandler(ClassCastException ex){
        return resultFormat(3,ex,"系统内部故障，请联系管理员");
    }

    @ExceptionHandler(IOException.class)
    public Result iOExceptionHandler(IOException ex){
        return resultFormat(4,ex,"系统内部故障，请联系管理员");
    }

    //未知方法异常
    @ExceptionHandler(NoSuchFieldException.class)
    public Result noSuchMethodExceptionHandler(NoSuchFieldException ex){
        return resultFormat(5,ex,"系统内部故障，请联系管理员");
    }

    //数组越界
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public Result indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex){
        return resultFormat(6,ex,"系统内部故障，请联系管理员");
    }

    //400错误
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public Result requestNotReadable(HttpMessageNotReadableException ex){
        return resultFormat(7,ex,"系统内部故障，请联系管理员");
    }

    //400错误
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public Result requestMissingServletRequest(MissingServletRequestParameterException ex){
        return resultFormat(9,ex,"系统内部故障，请联系管理员");
    }

    //405错误
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public Result request405(HttpRequestMethodNotSupportedException ex){
        return resultFormat(10,ex,"系统内部故障，请联系管理员");
    }

    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public Result request406(HttpMediaTypeNotAcceptableException ex){
        return resultFormat(11,ex,"系统内部故障，请联系管理员");
    }

    //500错误
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public Result server500(RuntimeException ex){
        return resultFormat(12,ex,"系统内部故障，请联系管理员");
    }

    //栈溢出
    @ExceptionHandler({StackOverflowError.class})
    public Result requestStackOverflow(StackOverflowError ex){
        return resultFormat(13,ex,"系统内部故障，请联系管理员");
    }

    //除数不能为0
    @ExceptionHandler({ArithmeticException.class})
    public Result arithmeticException(ArithmeticException ex){
        return resultFormat(13,ex,"系统内部故障，请联系管理员");
    }

    //其他错误
    @ExceptionHandler({Exception.class})
    public Result exception(Exception ex){
        return resultFormat(14,ex,"系统内部故障，请联系管理员");
    }

    @ExceptionHandler({NoHandlerFoundException.class})
    public Result noHandlerFoundException(HttpServletRequest request,Exception ex){
        return resultFormat(15,ex,"请求路径不存在");
    }
    @ExceptionHandler({BusinessException.class})
    public Result nonono(BusinessException e){
        return resultFormat(-1,e,e.getMsgCN());
    }

    private <T extends Throwable> Result resultFormat(Integer code, T ex,String msg){
        ex.printStackTrace();
        log.error(String.format(logExceptionFormat,code,ex.getMessage()));
        return new Result<String>(code,"ERROR",msg);
    }
}
